import re,time


# A类
def subnet_A(ip, count_1, l_file):
    "获取A类ip地址及子网掩码，写入各子网的地址范围"
    count_1_net = 8
    count_0 = 32 - count_1  # 子网掩码中0的个数
    num_subnet = 2 ** (count_1 - count_1_net)
    for i in range(0, 4):
        ip[i] = [ip[i]] * num_subnet
    temp = int(count_1 / 8)
    for i in range(int(count_1_net / 8), 4):
        ip[i] = [0] * len(ip[i])
    n_l = count_1 - 8 * temp
    n_r = 8 - n_l
    num_zj = 2 ** n_r
    for n in range(1, num_subnet):
        if count_0 > 16:
            ip[temp][n] = ip[temp][n - 1] + num_zj
        else:
            if 8 < count_0 <= 16:
                ip[temp][n] = ip[temp][n - 1] + num_zj
                ip[temp - 1][n] = ip[temp - 1][n - 1]
                if ip[temp][n] > 255:
                    ip[temp - 1][n] += 1
                    ip[temp][n] -= 256
            else:
                ip[temp][n] = ip[temp][n - 1] + num_zj
                ip[temp - 1][n] = ip[temp - 1][n - 1]
                ip[temp - 2][n] = ip[temp - 2][n - 1]
                if ip[temp][n] > 255:
                    ip[temp - 1][n] += 1
                    ip[temp][n] -= 256
                if ip[temp - 1][n] > 255:
                    ip[temp - 2][n] += 1
                    ip[temp - 1][n] -= 256
    for n in range(0, num_subnet):
        if count_0 > 16:
            l_file.writelines(['网络号:',str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]),'.', str(ip[3][n]),'\n'])
            l_file.writelines(['地址范围:',str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]),'.', str(ip[3][n]+1),'~'])
            l_file.writelines([str(ip[0][0]),'.', str(ip[1][n]+num_zj-1),'.', '255','.', '254','\n\n'])
        else:
            if 8 < count_0 < 16:
                l_file.writelines(['网络号:',str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]),'.', str(ip[3][n]),'\n'])
                l_file.writelines(['地址范围:',str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]),'.', str(ip[3][n]+1),'~'])
                l_file.writelines([str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]+num_zj-1),'.', '254','\n\n'])
            else:
                l_file.writelines(['网络号:',str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]),'.', str(ip[3][n]),'\n'])
                l_file.writelines(['地址范围:',str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]),'.', str(ip[3][n]+1),'~'])
                l_file.writelines([str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]),'.', str(ip[3][n] + num_zj -2),'\n\n'])
    return(num_subnet, num_zj*256**(3-temp))


# B类
def subnet_B(ip, count_1, l_file):
    "获取B类ip地址及子网掩码，写入各子网的地址范围"
    count_1_net = 16
    count_0 = 32 - count_1  # 子网掩码中0的个数
    num_subnet = 2 ** (count_1 - count_1_net)
    for i in range(0, 4):
        ip[i] = [ip[i]] * num_subnet
    temp = int(count_1 / 8)
    for i in range(int(count_1_net / 8), 4):
        ip[i] = [0] * len(ip[i])
    n_l = count_1 - 8 * temp
    n_r = 8 - n_l
    num_zj = 2 ** n_r
    n = 0
    l_file.writelines(['网络号:', str(ip[0][0]), '.', str(ip[1][0]), '.', str(ip[2][n]), '.', str(ip[3][0]),'\n'])
    l_file.writelines(['地址范围:', str(ip[0][0]), '.', str(ip[1][0]), '.', str(ip[2][n]), '.', str(ip[3][0]+1),'~'])
    if count_0 > 8:
        l_file.writelines([str(ip[0][0]), '.', str(ip[1][0]), '.', str(ip[2][n]) + str(num_zj - 1), '.', '254'',\n\n'])
    else:
        l_file.writelines([str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]),'.', str(ip[3][n]+num_zj-2),'\n\n'])
    for n in range(1, num_subnet):
        if count_0 > 8:
            ip[temp][n] = ip[temp][n - 1] + num_zj
            l_file.writelines(['网络号:', str(ip[0][0]), '.', str(ip[1][0]), '.', str(ip[2][n]), '.', str(ip[3][0]),'\n'])
            l_file.writelines(['地址范围:', str(ip[0][0]), '.', str(ip[1][0]), '.', str(ip[2][n]), '.', str(ip[3][0]+1),'~'])
            l_file.writelines([str(ip[0][0]), '.', str(ip[1][0]), '.', str(ip[2][n] + num_zj - 1), '.', '254','\n\n'])
        else:
            ip[temp][n] = ip[temp][n - 1] + num_zj
            ip[temp - 1][n] = ip[temp - 1][n - 1]
            if ip[temp][n] > 255:
                ip[temp - 1][n] += 1
                ip[temp][n] -= 256
            l_file.writelines(['网络号:', str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]),'.', str(ip[3][n]),'\n'])
            l_file.writelines(['地址范围:', str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]),'.', str(ip[3][n]+1),'~'])
            l_file.writelines([str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]),'.', str(ip[3][n]+num_zj-2),'\n\n'])
    return(num_subnet, num_zj*256**(3-temp))


# C类
def subnet_C(ip, count_1, l_file):
    "获取C类ip地址及子网掩码，写入各子网的地址范围"
    count_1_net = 24
    num_subnet = 2 ** (count_1 - count_1_net)  # 子网数为2**子网掩码中1的个数-默认子网掩码中的）
    for i in range(0, 4):
        ip[i] = [ip[i]] * num_subnet
    temp = int(count_1 / 8)
    for i in range(int(count_1_net / 8), 4):
        ip[i] = [0] * len(ip[i])
    n_l = count_1 - 8 * temp
    n_r = 8 - n_l
    num_zj = 2 ** n_r
    n = 0
    l_file.writelines(['网络号:',str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]),'.', str(ip[3][n]),'\n'])
    l_file.writelines(['地址范围:',str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]),'.', str(ip[3][n]+1),'~'])
    l_file.writelines([str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]),'.', str(ip[3][n] + num_zj -2),'\n\n'])
    for n in range(1, num_subnet):
        ip[temp][n] = ip[temp][n - 1] + num_zj
        l_file.writelines(['网络号:',str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]),'.', str(ip[3][n]),'\n'])
        l_file.writelines(['地址范围:',str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]),'.', str(ip[3][n]+1),'~'])
        l_file.writelines([str(ip[0][0]),'.', str(ip[1][n]),'.', str(ip[2][n]),'.', str(ip[3][n] + num_zj -2),'\n\n'])
    return(num_subnet,num_zj)


# 输入的点分十进制的IP地址被存储为字符串的格式，转换为不包含点的十进制整形数组
def ip_depart(ip_temp):
    "输入点分十进制，返回四段十进制数"
    ip_temp_depart = re.split(r'[./]', ip_temp)
    ip_d_depart = []
    for i in range(0, len(ip_temp_depart), 1):
        ip_d_depart.append(int(ip_temp_depart[i]))
    return ip_d_depart


def subnet(net_id, type_ip, count_1):
    "获取IP地址及其类型和掩码中1的数量，调用相应的函数"
    f = open('F:\\ip_list.txt', 'w+')
    now = int(time.time())
    time_local = time.localtime(now)
    dt = time.strftime("%Y-%m-%d %H:%M:%S",time_local)
    f.writelines([dt,'\n'])
    if type_ip == 1:
        [num_sub,num_zw] = subnet_A(net_id,count_1, f)
    else:
        if type_ip == 2:
            [num_sub,num_zw] = subnet_B(net_id,count_1, f)
        else:
            [num_sub,num_zw] = subnet_C(net_id,count_1, f)
    print('共有',num_sub,'个子网,每个子网中主机数为',num_zw-2)
    print('各子网网络号，网络范围，可在F:\\ip_list.txt查看')

def type_ip_judge(ip):
    "判断网络类型"
    type_ip = 0
    temp = ip[0]
    if temp >= 0 and temp < 128:    # temp为ip地址的第一个字节
        print('\n该网络为A类网络')
        type_ip = 1
    else:
        if temp < 192:
            print('\n该网络为B类网络') 
            type_ip = 2
        else:
            print('\n该网络为C类网络')
            type_ip = 3
    return(type_ip)


def cla_net_id(zwym, ip):
    "通过二进制与运算计算网络地址"
    temp4 = 0 
    temp3 = 0 
    temp2 = ''
    net_id = [1,1,1,1]
    for i in range(0, 4):
        temp2 = bin(int(zwym[i]))
        temp4 = temp2.count('1') 
        temp3 = temp3 + temp4
    for i in range(0,4) :
        net_id[i] = (int(ip[i]) & (zwym[i])) # 与运算
    count_1 = temp3
    return(net_id,count_1)


def legal_check(ip_in, zwym_in):
    "检查IP地址及子网掩码的合法性"
    time1 = 3
    time2 = 3
    while time1 > 0 and time2 >0 :
            for i in range(0,4) :
                ip = ip_depart(ip_in)
                if int(ip[i]) >255 or int(ip[i]) < 0 :
                    time1 -= 1
                    ip_in = input('请重新输入IP：')
                else:
                    time1 = 0
            for j in range(0,4) :
                zwym = ip_depart(zwym_in)
                if int(zwym[0]) >255 or int(zwym[0]) < 0 :
                    time2 -= 1
                    zwym_in = input('请重新输入子网掩码：')
                else :
                    if int(zwym[j]) >255 or int(zwym[j]) < 0 :
                        time2 -= 1
                        zwym_in = input('请重新输入子网掩码：')
                    else:
                        time2 = 0
    return[ip,zwym,ip_in,zwym_in]


# main
ip_in = input('输入IP地址：')
zwym_in = input('输入子网掩码：')
[ip_l, zwym,ip_in,zwym_in] = legal_check(ip_in, zwym_in)  # 判断合法性
type_ip = type_ip_judge(ip_l) # 判断网络类型
[net_id, count_1] = cla_net_id(zwym,ip_l)
print('网络地址为',net_id[0],'.',net_id[1],'.',net_id[2],'.',net_id[3]) # 显示网络地址
subnet(net_id, type_ip, count_1)
